﻿/*
 * 居正 EQ600 电表
 * copyright by changli.xiao
 * */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Interfaces;
using System.Threading;
using System.Data;
using JN.Utility;
using System.IO.Ports;
using Power.Common;
namespace Power.MeterControl
{
    public class MeterEQ600:IMeter
    {
        #region property        
        public delegate void UpdateStatusHandler(MsgType msgType, object msg);
        public static event UpdateStatusHandler UpdateStatus;

        private Thread readThread;
        private object lockRead = new object();
        private Thread doProcessThread;
        private object lockDoProcess = new object();
        private Thread doFailedThread;
        private object lockFailedProcess = new object();

        private Manager.SystemStatus sysStatus = Manager.SystemStatus.Instance;
        private List<SerialPort> listCom = new List<SerialPort>();   //用于记录所有的serialport
        private List<Meter_Str> listTempData = new List<Meter_Str>();  //用于记录临时数据
        private List<Read_Failed> listReadFilaed = new List<Read_Failed>();   //用于记录不能读到的数据
        private List<string> listHead = new List<string>();    //用于记录电表head
        private List<int> listNode = new List<int>();      //用于记录多少节点
        private Dictionary<string, Meter_Comm_Error> dicCommFailed = new Dictionary<string, Meter_Comm_Error>(500);
        private int cur_hour=-1;  //当前小时
        //private int cur_min=0;   //当前分钟
        private const string param_Command = "0301040005";

        BLL.Com_infoBLL comBLL = new BLL.Com_infoBLL();
        private MeterCommon portComm = MeterCommon.Instance;
        private DataTable dtMeter;
        BLL.Meter_infoBLL meterBLL = new BLL.Meter_infoBLL();
        BLL.Meter_h_dataBLL hourDataBLL = new BLL.Meter_h_dataBLL();
        BLL.Meter_r_dataBLL realDataBLL = new BLL.Meter_r_dataBLL();
        BLL.Sys_alarmBLL alarmBLL = new BLL.Sys_alarmBLL();
        #endregion
        private static MeterEQ600 instance = null;
        private static readonly object plcLock = new object();
        public static MeterEQ600 Instance
        {
            get
            {
                lock (plcLock)
                {
                    if (instance == null)
                    {
                        instance = new MeterEQ600();
                    }
                    return instance;
                }
            }
        }

        private MeterEQ600()
        {

        }

        #region do funcs
        private void StartThread()
        {
            if (readThread == null)
            {
                readThread = new Thread(new ThreadStart(ReadMeter));
                readThread.Name = "Meter Read Thread";
                readThread.IsBackground = true;
                readThread.Start();
            }
        }
        private void ReadMeter()
        {
            while (true)
            {
                if (sysStatus.IsStartRead)
                {
                    ReadFun();
                }
                else
                {
                    Thread.Sleep(1000);
                }
            }
        }
        private void ReadFun()
        {
            lock (lockRead)
            {
                DateTime startTime = DateTime.Now;
                try
                {
                    //1. get this sation com port list
                    GetCommPort();
                    //2. open all port
                    if (listCom.Count <= 0)
                    {
                        SystemLogger.Write(LogType.Error,"Error: Com port is none","ReadFun");
                        Common.Notify.NotifyMessage.Show("系统错误", "系统设定COM端口错误",true);
                        return;
                    }
                    if (listCom.Count != listHead.Count && listCom.Count!= listNode.Count)
                    {
                        SystemLogger.Write(LogType.Error, "Error: Com data length error. com count:"+listCom.Count +" head count:"+listHead.Count+" node count:"+listNode.Count, "ReadFun");
                        Common.Notify.NotifyMessage.Show("系统错误", "系统设定错误. com count" + listCom.Count + " head count:" + listHead.Count + " node count:" + listNode.Count, true);
                        return;
                    }                    
                    //3. loop all port/all node read current data from one port,save to list
                    for (int i = 0; i < listCom.Count; i++)
                    {
                        string revMessage="" ;
                        string writeData = "";
                        //string paramData = "";
                        string revParaData= "";
                        bool ret;
                        SerialPort temport = listCom[i];
                        for (int j = 0; j < listNode[i]; j++)
                        {
                            //read param
                            string pa_command = (j + 1).ToString("X").PadLeft(2, '0') + param_Command;
                            ret = portComm.Write(temport, pa_command, ref revParaData);
                            if (!ret)
                            {
                                SystemLogger.Write(LogType.Error, "Error,Read Com Data Failed." + temport.PortName + "-" + writeData, "ReadFun");
                                Read_Failed failed_data = new Read_Failed();
                                failed_data.Com_Port = temport.PortName;
                                failed_data.Node = j + 1;
                                listReadFilaed.Add(failed_data);
                            }
                            else
                            {
                                string x = (j + 1).ToString("X");
                                writeData = listHead[i].Replace("##", x.PadLeft(2, '0'));
                                ret = portComm.Write(temport, writeData, ref revMessage);
                                if (!ret)
                                {
                                    SystemLogger.Write(LogType.Error, "Error,Read Com Data Failed." + temport.PortName + "-" + writeData, "ReadFun");
                                    Read_Failed failed_data = new Read_Failed();
                                    failed_data.Com_Port = temport.PortName;
                                    failed_data.Node = j + 1;
                                    listReadFilaed.Add(failed_data);
                                }
                                else
                                {
                                    //add to list
                                    Meter_Str temp = new Meter_Str();
                                    temp.Com_Port = temport.PortName;
                                    temp.Meter_Data = revMessage;
                                    temp.Param_Data = revParaData;
                                    listTempData.Add(temp);
                                }
                            }
                        }
                    }
                    
                }
                catch (Exception ex)
                {
                    SystemLogger.Write(ex);
                }
                finally
                {
                    TimeSpan useTime = DateTime.Now - startTime;
                    SystemLogger.Write(LogType.Flow, "One flow use time:"+useTime.TotalMilliseconds, "ReadFun");
                    //4. do sleep                     
                    Thread.Sleep(1000);
                }
            }
        }
        public void GetCommPort()
        {
            try
            {
                if (sysStatus.IsChangCom)
                {
                    //clear all data
                    listCom.Clear();
                    listHead.Clear();
                    listNode.Clear();

                    StringBuilder sql= new StringBuilder();
                    sql.Append(" station_id='" + sysStatus.Station_id + "' and scan_cycle=1 ");
                    DataTable dt = comBLL.GetList(sql.ToString()).Tables[0];
                    if (dt.Rows.Count <= 0) return;
                    for (int i = 0; i < dt.Rows.Count; i++)
                    {
                        try
                        {
                            //get port info
                            SerialPort port = new SerialPort();
                            port.PortName = dt.Rows[i]["com_port"].ToString();
                            port.BaudRate = int.Parse(dt.Rows[i]["baud_rate"].ToString());
                            port.DataBits = int.Parse(dt.Rows[i]["data_bit"].ToString());
                            switch (dt.Rows[i]["odd"].ToString().ToUpper())
                            {
                                case "NONE":
                                    port.Parity = Parity.None;
                                    break;
                                case "ODD":
                                    port.Parity = Parity.Odd;
                                    break;
                                case "EVEN":
                                    port.Parity = Parity.Even;
                                    break;
                            }
                            switch (dt.Rows[i]["stop_bit"].ToString())
                            {
                                case "1":
                                    port.StopBits = StopBits.One;
                                    break;
                                case "1.5":
                                    port.StopBits = StopBits.OnePointFive;
                                    break;
                                case "2":
                                    port.StopBits = StopBits.Two;
                                    break;
                            }
                            port.ReadTimeout = 500;
                            port.WriteTimeout = 500;
                            //port.Open();   //open all port
                            //add to list
                            listCom.Add(port);
                            listHead.Add(dt.Rows[i]["read_head"].ToString());
                            listNode.Add(int.Parse(dt.Rows[i]["node_count"].ToString()));
                        }
                        catch (Exception ex)
                        {
                            SystemLogger.Write(ex);    
                        }
                    }
                    sysStatus.IsChangCom = false;
                }
            }
            catch (Exception ex)
            {
                SystemLogger.Write(ex);
            }
        }
        private void StartDoThread()
        {
            if (doProcessThread == null)
            {
                doProcessThread = new Thread(new ThreadStart(DoProcess));
                doProcessThread.Name = "Do Process Thread";
                doProcessThread.IsBackground = true;
                doProcessThread.Start();
            }
        }
        private void DoProcess()
        {
            while (true)
            {
                if (sysStatus.IsStartRead)
                {
                    DoProcessFun();
                }
                else
                {
                    Thread.Sleep(1000);
                }
            }
        }
        private void DoProcessFun()
        {
            lock (lockDoProcess)
            {
                DateTime startTime = DateTime.Now;
                try
                {
                    //1. check list data
                    if (listTempData.Count <= 0) return;
                    //2. get get one data
                    Meter_Str tempData = listTempData[0];                    
                    //3. analyse one data
                    int type;
                    if (tempData.Com_Port != "COM1" || tempData.Com_Port != "COM2")
                    {
                        type = 1;
                    }
                    else
                    {
                        type = 2;
                    }
                    RealData_EQ600 realData = AnalyseData(tempData.Meter_Data, tempData.Param_Data);
                    //RealData_PMH630 realData = AnalyseData(tempData.Meter_Data, type); 
                    //4. save data to db
                    string metet_id = GetMeterID(tempData.Com_Port,tempData.Meter_Data.Substring(0,2));
                    realData.meter_id = metet_id;
                    bool ret = SaveReal2DB(realData);
                    //5. delete from list
                    if (ret)
                    {
                        //success,delete one data
                        listTempData.RemoveAt(0);
                    }
                    else
                    {
                        //failed
                        SystemLogger.Write(LogType.Error, "Save to db failed,data:" + tempData.Meter_Data, "DoProcessFun");
                        //remove data
                        listTempData.RemoveAt(0);
                    }
                    //check time is at hour end
                    if (DateTime.Now.Hour > cur_hour)
                    {
                        if (DateTime.Now.Minute > 58)
                        {
                            SaveHourData2DB();
                            cur_hour = DateTime.Now.Hour;
                            if (cur_hour >= 23)
                            {
                                cur_hour = -1;
                            }
                        }
                    }
                    //6. do next data
                }
                catch (Exception ex)
                {
                    SystemLogger.Write(ex);
                }
                finally
                {
                    TimeSpan useTime = DateTime.Now - startTime;
                    SystemLogger.Write(LogType.Flow, "Do process time "+ useTime.TotalMilliseconds, "DocProcess");
                    Thread.Sleep(500);
                }
            }
        }
        private void StartFailedData()
        {
            if (doFailedThread == null)
            {
                doFailedThread = new Thread(new ThreadStart(DoFailedProcess));
                doFailedThread.Name = "Do Failed Thread";
                doFailedThread.IsBackground = true;
                doFailedThread.Start();
            }
        }
        private void DoFailedProcess()
        {
            while (true)
            {
                if (sysStatus.IsStartRead)
                {
                    DoFailedProcessFun();
                }
                else
                {
                    Thread.Sleep(1000);
                }
            }
        }
        private void DoFailedProcessFun()
        {
            lock (lockFailedProcess)
            {
                DateTime startTime = DateTime.Now;
                try
                {
                    //1. check list data
                    if (listReadFilaed.Count < 10) return;
                    //2. get get one data  
                    int count = listReadFilaed.Count;
                    bool ret=true;
                    for (int i = 0; i < 10;i++ )
                    {
                        //get all failed
                        Read_Failed tempData = listReadFilaed[i];
                        string meter_id = GetMeterID(tempData.Com_Port, tempData.Node.ToString());
                        if (meter_id != "")
                        {
                            //save to dic
                            if (dicCommFailed.ContainsKey(meter_id))
                            {
                                Meter_Comm_Error temp = dicCommFailed[meter_id];
                                temp.read_failed_count++;
                                if (temp.read_failed_count < sysStatus.IgnoreCount)
                                {
                                    temp.is_show = true;
                                }
                                dicCommFailed[meter_id] = temp;
                                //dicCommFailed.Remove(meter_id);
                                //dicCommFailed.Add(meter_id, temp);
                            }
                            else
                            {
                                Meter_Comm_Error temp = new Meter_Comm_Error();
                                temp.is_show = true;
                                temp.meter_id = meter_id;
                                temp.read_failed_count = 1;
                                dicCommFailed.Add(meter_id, temp);
                            }
                            ret = SaveMeterReadFailed(meter_id);
                        }
                        else
                        {
                            SystemLogger.Write(LogType.Error, "loop failed data error.meter :" + meter_id, "DoFailedProcessFun");                            
                        }
                    }                    
                    //remove 10
                    listReadFilaed.RemoveRange(0, 10);                    

                    Thread.Sleep(300);

                    //show form 
                    foreach (string id in dicCommFailed.Keys)
                    {
                        Meter_Comm_Error data = dicCommFailed[id];
                        if (data.is_show && !sysStatus.IsIgnoreAlarm)
                        {
                            //show msg
                            //Common.Notify.NotifyMessage.ShowNoDialog("电表通信失败", "电表通信失败.电表:" + data.meter_id);
                            //System.Windows.Forms.Application.DoEvents();
                            //Thread.Sleep(30);
                            ThrowMessage(MsgType.ShowEvent, (object)"电表通信失败.电表:" + data.meter_id);
                            data.is_show = false;
                            dicCommFailed[id] = data;
                            break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    SystemLogger.Write(ex);
                }
                finally
                {
                    TimeSpan useTime = DateTime.Now - startTime;
                    SystemLogger.Write(LogType.Flow, "Do failed process time " + useTime.TotalMilliseconds, "DocFailedProcess");
                    Thread.Sleep(1000);
                }
            }
        }
        private RealData_EQ600 AnalyseData(string data1,string param1)
        {
            RealData_EQ600 ret = new RealData_EQ600();
            try
            {                
                if (param1.Length < 12)
                {
                    SystemLogger.Write(LogType.Error,"Meter param1 data < 20,data :"+param1,"AnalysieData");
                    return ret;
                }
                if (data1.Length < 210)
                {
                    SystemLogger.Write(LogType.Error,"Meter real data < 210,data :"+data1,"AnalysieData");
                    return ret;
                }
                //get param data
                Param_EQ600 param = new Param_EQ600();
                param.Ctn = Convert.ToInt32(param1.Substring(6, 4), 16);
                param.Pt1 = Convert.ToInt32(param1.Substring(10, 4), 16) * 10000 + Convert.ToInt32(param1.Substring(14, 4), 16);
                param.Pt2 = Convert.ToInt32(param1.Substring(18, 4), 16);
                param.Ct1 = Convert.ToInt32(param1.Substring(22, 4), 16); ;

                //get meter data;               
                //居正电表EQ630                
                //F
                ret.F = (float)Convert.ToInt32(data1.Substring(6, 4), 16) / 100;
                //v
                float vVar = (float)param.Pt1 / param.Pt2 / 10;
                ret.V_a = (float)Convert.ToInt32(data1.Substring(10, 4), 16) * vVar;
                ret.V_b = (float)Convert.ToInt32(data1.Substring(14, 4), 16) * vVar;
                ret.V_c = (float)Convert.ToInt32(data1.Substring(18, 4), 16) * vVar;
                ret.V_avg = (float)Convert.ToInt32(data1.Substring(22, 4), 16) * vVar;

                //u
                ret.U_ab = (float)Convert.ToInt32(data1.Substring(26, 4), 16) * vVar;
                ret.U_bc = (float)Convert.ToInt32(data1.Substring(30, 4), 16) * vVar;
                ret.U_ca = (float)Convert.ToInt32(data1.Substring(34, 4), 16) * vVar;
                ret.U_avg = (float)Convert.ToInt32(data1.Substring(38, 4), 16) * vVar;

                //i
                float iVar = (float)param.Ct1 / 5 / 1000;
                ret.I_a = (float)Convert.ToInt32(data1.Substring(42, 4), 16) * iVar;
                ret.I_b = (float)Convert.ToInt32(data1.Substring(46, 4), 16) * iVar;
                ret.I_c = (float)Convert.ToInt32(data1.Substring(50, 4), 16) * iVar;
                ret.I_avg = (float)Convert.ToInt32(data1.Substring(54, 4), 16) * iVar;
                ret.I_d = (float)Convert.ToInt32(data1.Substring(58, 4), 16) * iVar;

                //p
                float pVar = (float)param.Pt1 / param.Pt2 * param.Ct1 / param.Ctn;
                ret.P_a = (float)Convert.ToInt32(data1.Substring(62, 4), 16) * pVar;
                ret.P_b = (float)Convert.ToInt32(data1.Substring(66, 4), 16) * pVar;
                ret.P_c = (float)Convert.ToInt32(data1.Substring(70, 4), 16) * pVar;
                ret.P_t = (float)Convert.ToInt32(data1.Substring(74, 4), 16) * pVar;
                //q
                ret.Q_a = (float)Convert.ToInt32(data1.Substring(78, 4), 16) * pVar;
                ret.Q_b = (float)Convert.ToInt32(data1.Substring(82, 4), 16) * pVar;
                ret.Q_c = (float)Convert.ToInt32(data1.Substring(86, 4), 16) * pVar;
                ret.Q_t = (float)Convert.ToInt32(data1.Substring(90, 4), 16) * pVar;
                //s
                ret.S_a = (float)Convert.ToInt32(data1.Substring(94, 4), 16) * pVar;
                ret.S_b = (float)Convert.ToInt32(data1.Substring(98, 4), 16) * pVar;
                ret.S_c = (float)Convert.ToInt32(data1.Substring(102, 4), 16) * pVar;
                ret.S_t = (float)Convert.ToInt32(data1.Substring(106, 4), 16) * pVar;

                //pf
                ret.PF_a=(float)Convert.ToInt32(data1.Substring(110, 4), 16)/1000;
                ret.PF_b = (float)Convert.ToInt32(data1.Substring(114, 4), 16) / 1000;
                ret.PF_c = (float)Convert.ToInt32(data1.Substring(118, 4), 16) / 1000;
                ret.PF = (float)Convert.ToInt32(data1.Substring(122, 4), 16) / 1000;

                //U_unbl
                ret.U_unbl = (float)Convert.ToInt32(data1.Substring(126, 4), 16);
                ret.I_unbl = (float)Convert.ToInt32(data1.Substring(130, 4), 16);
                //负载性质
                ret.Load_type = Convert.ToInt32(data1.Substring(134, 4), 16);
                //P_dema
                ret.P_dema = (float)Convert.ToInt32(data1.Substring(138, 4), 16);
                ret.Q_dema = (float)Convert.ToInt32(data1.Substring(142, 4), 16);
                ret.S_dema = (float)Convert.ToInt32(data1.Substring(146, 4), 16);

                //DI,DO
                ret.DI = Convert.ToInt32(data1.Substring(150, 4), 16);
                ret.DO = Convert.ToInt32(data1.Substring(154, 4), 16);

                //有功电度
                ret.Imp_A = ((float)Convert.ToInt32(data1.Substring(158, 4), 16) * 65535 + (float)Convert.ToInt32(data1.Substring(162, 4), 16))/10;
                ret.Exp_A = ((float)Convert.ToInt32(data1.Substring(166, 4), 16) * 65535 + (float)Convert.ToInt32(data1.Substring(170, 4), 16))/10;
                ret.Imp_R = ((float)Convert.ToInt32(data1.Substring(174, 4), 16) * 65535 + (float)Convert.ToInt32(data1.Substring(178, 4), 16)) / 10;
                ret.Exp_R = ((float)Convert.ToInt32(data1.Substring(182, 4), 16) * 65535 + (float)Convert.ToInt32(data1.Substring(186, 4), 16)) / 10;

                ret.Ep_total = ((float)Convert.ToInt32(data1.Substring(190, 4), 16) * 65535 + (float)Convert.ToInt32(data1.Substring(194, 4), 16)) / 10;
                ret.Eq_net = ((float)Convert.ToInt32(data1.Substring(198, 4), 16) * 65535 + (float)Convert.ToInt32(data1.Substring(202, 4), 16)) / 10;
                ret.Eq_total = ((float)Convert.ToInt32(data1.Substring(206, 4), 16) * 65535 + (float)Convert.ToInt32(data1.Substring(210, 4), 16)) / 10;
                ret.Eq_net = ((float)Convert.ToInt32(data1.Substring(214, 4), 16) * 65535 + (float)Convert.ToInt32(data1.Substring(218, 4), 16)) / 10;
                
                //赋值属性
                ret.Ct1 = param.Ct1;
                ret.Ctn = param.Ctn;
                ret.Pt1 = param.Pt1;
                ret.Pt2 = param.Pt2;

                return ret;
            }
            catch (Exception ex)
            {
                SystemLogger.Write(ex);
                return ret ;
            }
        }
        private string GetMeterID(string port, string node)
        {
            string ret= "";
            try
            {
                if (dtMeter == null || dtMeter.Rows.Count <= 0)
                {
                    dtMeter = meterBLL.GetList(" station_id='" + sysStatus.Station_id + "' ").Tables[0];
                }
                //根据com和node 查找id；
                int _node = Convert.ToInt32(node, 16);
                DataRow[] datarows = dtMeter.Select(" com_port ='"+port+"' and node ='"+_node+"' ");
                if (datarows.Length > 0)
                {
                    ret = datarows[0]["meter_id"].ToString();
                }
                return ret;
            }catch(Exception ex)
            {
                SystemLogger.Write(ex);
                return ret;
            }
        }
        private bool SaveReal2DB(RealData_EQ600 data)
        {
            bool ret = false;
            try
            {
                Model.Meter_r_data mR = realDataBLL.GetModel(sysStatus.Station_id, data.meter_id);
                if (mR == null)
                {
                    //new one
                    mR = new Model.Meter_r_data();
                    mR.ct1 = data.Ct1;
                    mR.evt_time = DateTime.Now;
                    mR.exp_a =(decimal)data.Exp_A;
                    mR.exp_r = (decimal)data.Exp_R;
                    mR.f = (decimal)data.F;
                    mR.i_a  = (decimal)data.I_a;
                    mR.i_avg = (decimal)data.I_avg;
                    mR.i_b = (decimal)data.I_b;
                    mR.i_c = (decimal)data.I_c;
                    mR.i_d = (decimal)data.I_d;
                    mR.imp_a = (decimal)data.Imp_A;
                    mR.imp_r = (decimal)data.Imp_R;
                    mR.meter_id = data.meter_id;
                    mR.p_a = (decimal)data.P_a;
                    mR.p_b = (decimal)data.P_b;
                    mR.p_c = (decimal)data.P_c;
                    mR.p_t = (decimal)data.P_t;
                    mR.pf = (decimal)data.PF;
                    mR.pf_a = (decimal)data.PF_a;
                    mR.pf_b = (decimal)data.PF_b;
                    mR.pf_c = (decimal)data.PF_c;
                    mR.pt1_ = data.Pt1;
                    mR.pt2 = data.Pt2;
                    mR.q_a = (decimal)data.Q_a;
                    mR.q_b = (decimal)data.Q_b;
                    mR.q_c = (decimal)data.Q_c;
                    mR.q_t = (decimal)data.Q_t;
                    mR.relay_data = data.DI;
                    mR.s_a = (decimal)data.S_a;
                    mR.s_b = (decimal)data.S_b;
                    mR.s_c = (decimal)data.S_c;
                    mR.s_t = (decimal)data.S_t;
                    mR.station_id = sysStatus.Station_id;
                    mR.status = 1;   //在线
                    mR.swith_data = data.DO;
                    mR.u_ab = (decimal)data.U_ab;
                    mR.u_avg = (decimal)data.U_avg;
                    mR.u_bc = (decimal)data.U_bc;
                    mR.u_ca = (decimal)data.U_ca;
                    mR.v_a = (decimal)data.V_a;
                    mR.v_avg = (decimal)data.V_avg;
                    mR.v_b = (decimal)data.V_b;
                    mR.v_c = (decimal)data.V_c;
                    //new field
                    mR.u_unbl = (decimal)data.U_unbl;
                    mR.i_unbl =(decimal)data.I_unbl;
                    mR.load_type =data.Load_type;
                    mR.p_dema =(decimal)data.P_dema;
                    mR.q_dema=(decimal)data.Q_dema;
                    mR.s_dema=(decimal)data.S_dema;
                    mR.ep_total=(decimal)data.Ep_total;
                    mR.ep_net=(decimal)data.Ep_net;
                    mR.eq_total=(decimal)data.Eq_total;
                    mR.eq_net = (decimal)data.Eq_net;
                    
                    ret = realDataBLL.Add(mR);
                }
                else
                {
                    //update one                    
                    mR.ct1 = data.Ct1;
                    mR.evt_time = DateTime.Now;
                    mR.exp_a = (decimal)data.Exp_A;
                    mR.exp_r = (decimal)data.Exp_R;
                    mR.f = (decimal)data.F;
                    mR.i_a = (decimal)data.I_a;
                    mR.i_avg = (decimal)data.I_avg;
                    mR.i_b = (decimal)data.I_b;
                    mR.i_c = (decimal)data.I_c;
                    mR.i_d = (decimal)data.I_d;
                    mR.imp_a = (decimal)data.Imp_A;
                    mR.imp_r = (decimal)data.Imp_R;
                    mR.meter_id = data.meter_id;
                    mR.p_a = (decimal)data.P_a;
                    mR.p_b = (decimal)data.P_b;
                    mR.p_c = (decimal)data.P_c;
                    mR.p_t = (decimal)data.P_t;
                    mR.pf = (decimal)data.PF;
                    mR.pf_a = (decimal)data.PF_a;
                    mR.pf_b = (decimal)data.PF_b;
                    mR.pf_c = (decimal)data.PF_c;
                    mR.pt1_ = data.Pt1;
                    mR.pt2 = data.Pt2;
                    mR.q_a = (decimal)data.Q_a;
                    mR.q_b = (decimal)data.Q_b;
                    mR.q_c = (decimal)data.Q_c;
                    mR.q_t = (decimal)data.Q_t;
                    mR.relay_data = data.DI;
                    mR.s_a = (decimal)data.S_a;
                    mR.s_b = (decimal)data.S_b;
                    mR.s_c = (decimal)data.S_c;
                    mR.s_t = (decimal)data.S_t;
                    mR.station_id = sysStatus.Station_id;
                    mR.status = 1;  //在线
                    mR.swith_data = data.DO;
                    mR.u_ab = (decimal)data.U_ab;
                    mR.u_avg = (decimal)data.U_avg;
                    mR.u_bc = (decimal)data.U_bc;
                    mR.u_ca = (decimal)data.U_ca;
                    mR.v_a = (decimal)data.V_a;
                    mR.v_avg = (decimal)data.V_avg;
                    mR.v_b = (decimal)data.V_b;
                    mR.v_c = (decimal)data.V_c;

                    //new field
                    mR.u_unbl = (decimal)data.U_unbl;
                    mR.i_unbl = (decimal)data.I_unbl;
                    mR.load_type = data.Load_type;
                    mR.p_dema = (decimal)data.P_dema;
                    mR.q_dema = (decimal)data.Q_dema;
                    mR.s_dema = (decimal)data.S_dema;
                    mR.ep_total = (decimal)data.Ep_total;
                    mR.ep_net = (decimal)data.Ep_net;
                    mR.eq_total = (decimal)data.Eq_total;
                    mR.eq_net = (decimal)data.Eq_net;

                    ret = realDataBLL.Update(mR);
                }
                return ret;
            }
            catch (Exception ex)
            {
                SystemLogger.Write(ex);
                return ret;                 
            }
        }
        private bool SaveHourData2DB()
        {
            bool ret = false;
            try
            {
                //do PROCEDURE

                IDataParameter[] parameter= new IDataParameter[1];
                parameter[0] = new System.Data.SqlClient.SqlParameter("@station_id", sysStatus.Station_id);
                //parameter[0] = sysStatus.Station_id;
                int count = 0;
                int cnt =DBUtility.DbHelperSQL.RunProcedure("proc_do_hour_data",parameter,out count);
                if (count > 0)
                {
                    ret = true;
                    SystemLogger.Write(LogType.Flow, "Save hour data to db,count:"+count, "SaveHourData2DB");
                }
                return ret;
            }
            catch (Exception ex)
            {
                SystemLogger.Write(ex);
                return ret;
            }
        }
        private bool SaveMeterReadFailed(string meter_id)
        {
            bool ret = false;
            try
            {
                Model.Sys_alarm mAlm = new Model.Sys_alarm();
                mAlm.alarm_device = meter_id;
                mAlm.alarm_info = "电表通信失败!";
                mAlm.alarm_time = DateTime.Now;
                mAlm.alarm_type = "Error";
                mAlm.station_id = sysStatus.Station_id;

                ret = alarmBLL.Add(mAlm) == 1 ? true : false; ;
                return ret;
            }
            catch (Exception ex)
            {
                SystemLogger.Write(ex);
                return ret;
            }
        }
        #endregion

        public bool Start()
        {
            StartThread();
            StartDoThread();
            StartFailedData();
            //sysStatus.IsStartRead = true;
            return true;
        }

        public bool Stop()
        {
            sysStatus.IsStartRead = false;
            return true;
        }

        public bool SetSerialPort(List<System.IO.Ports.SerialPort> lstPort)
        {
            throw new NotImplementedException();
        }


        public bool OpenPort()
        {
            bool ret = false;
            try
            {                
                //open all port
                int count = 0;
                for (int i = 0; i < listCom.Count; i++)
                {
                    try
                    {
                        if (!listCom[i].IsOpen)
                        {
                            listCom[i].Open();
                            count++;
                        }
                    }
                    catch (Exception ex)
                    {
                        SystemLogger.Write(ex);
                    }
                }
                if (count == listCom.Count)
                {
                    ret = true;
                }
                return ret;
            }
            catch (Exception ex)
            {
                SystemLogger.Write(ex);                
                return ret;
            }
        }
        public bool ClosePort()
        {
            bool ret = false;
            try
            {
                //open all port
                int count = 0;
                for (int i = 0; i < listCom.Count; i++)
                {
                    try
                    {
                        if (listCom[i].IsOpen)
                        {
                            listCom[i].Close();
                            count++;
                        }
                    }
                    catch (Exception ex)
                    {
                        SystemLogger.Write(ex);
                    }
                }
                if (count == listCom.Count)
                {
                    ret = true;
                }
                return ret;
            }
            catch (Exception ex)
            {
                SystemLogger.Write(ex);
                return ret;
            }
        }


        object IMeter.AnalyseData(string data1, string type)
        {
            return (object)AnalyseData(data1, type.ToString());
        }

        string IMeter.GetMeterID(string port, string node)
        {
            return GetMeterID(port, node);
        }

        public bool SaveReal2DB(object data)
        {
            RealData_EQ600 dat1 =(RealData_EQ600)data;
            return SaveReal2DB(dat1);
        }
        #region status event
        private void ThrowMessage(MsgType msgType, object msg)
        {
            if (UpdateStatus != null)
            {
                UpdateStatus(msgType, msg);
            }
        }
        #endregion
    }
}
